#include <GL/gl.h>

#include "hw_font.hpp"

namespace raja
{
namespace ttf2
{

using namespace raja::math;

hw_font::~hw_font()
{
	if( __chars.size() )
	{
		glDeleteTextures(1, &__texture_id);
	}
}

hw_font_ptr hw_font::create_instance(const ttf2::sw_font_ptr &fnt)
{
	uint32 tex_width	= fnt->get_whole_pixmap_width();
	uint32 tex_height	= fnt->get_whole_pixmap_height();
	const uint8*	tex_data	= fnt->get_whole_pixmap_data();

	GLuint			tex_id;

	// create opengl texture
	glGenTextures(1, &tex_id);
	glBindTexture(GL_TEXTURE_2D, tex_id);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_data);
//	gl_check();

	// set the texture parameters
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	hw_font_ptr	inst	= hw_font_ptr(new hw_font());

	inst->__texture_id	= tex_id;
	inst->__line_height	= real32(fnt->get_max_char_height());

	for( uint8 i = ttf2::sw_font::CHAR_START; i < ttf2::sw_font::CHAR_END; i++ )
	{
		real32	w	= real32(fnt->get_char_width(i));
		real32	h	= real32(fnt->get_char_height(i));

		real32	a	= real32(fnt->get_char_advance(i));

		ivec2 imin;
		ivec2 imax;

		fnt->get_char_bbox(i, imin, imax);

		// need some coordinate adjustment for our GL coordinate
		// system (origin is in the top-left of the screen)
		vec2	bmin(imin.x, inst->__line_height - imin.y);
		vec2	bmax(imax.x, inst->__line_height - imax.y);

		ivec2 uv_imin;
		ivec2 uv_imax;

		fnt->get_char_wp_bbox(i, uv_imin, uv_imax);

		// swapping of Vs is required also for the GL coordinate system
		vec2 uv_min(uv_imin.x, uv_imax.y);
		vec2 uv_max(uv_imax.x, uv_imin.y);

		uv_min.x	/= real32(tex_width);
		uv_min.y	/= real32(tex_height);

		uv_max.x	/= real32(tex_width);
		uv_max.y	/= real32(tex_height);


		__hw_char	_ch;
		_ch.uv_min	= uv_min;
		_ch.uv_max	= uv_max;
		_ch.advance	= a;

		_ch.bbox_min	= bmin;
		_ch.bbox_max	= bmax;

		inst->__chars.push_back(_ch);
	}


	return inst;
}

vec2 hw_font::draw_char(const vec2 &pos, uint8 ch) const
{
	uint8	i	= ch - ttf2::sw_font::CHAR_START;

	//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	glBegin(GL_QUADS);
	{
		vec2	uv_min	= __chars[i].uv_min;
		vec2	uv_max	= __chars[i].uv_max;

		vec2	b_min	= __chars[i].bbox_min;
		vec2	b_max	= __chars[i].bbox_max;

		//cout << "char " << char(ch) << ": < " << b_min.x << ", " << b_min.y << " > - < " << b_max.x << ", " << b_max.y << " >" << endl;

		b_min	+= pos;
		b_max	+= pos;

		glTexCoord2f(uv_min.x, uv_min.y);
		glVertex3f(b_min.x, b_min.y, 0);

		glTexCoord2f(uv_max.x, uv_min.y);
		glVertex3f(b_max.x, b_min.y, 0);


		glTexCoord2f(uv_max.x, uv_max.y);
		glVertex3f(b_max.x, b_max.y, 0);

		glTexCoord2f(uv_min.x, uv_max.y);
		glVertex3f(b_min.x, b_max.y, 0);
	} glEnd();

	return vec2(pos.x + __chars[i].advance, pos.y);
}

} // namespace ttf2
} // namespace raja
